﻿#if USEOLDFFMS2
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace SCOSub.FFMS2old
{

    class ffms2
    {

        private IntPtr index = IntPtr.Zero;

        IntPtr videobase;
        public VideoProperties videoproperties;
        AVFrameLite FrameCache;
        // static AudioProperties audioproperties;

        public void Load(string filename, IndexCallbackDelegate icd)
        {
            if (File.Exists(filename) == false)
                throw new Exception("文件不存在");
            Init();
            index = IntPtr.Zero;
            StringBuilder sb = new StringBuilder(1000);
            index = MakeIndex(filename, 0, 0, null, true, icd, IntPtr.Zero, sb, 1000u);
            if (index == IntPtr.Zero)
            {
                throw new Exception("MakeIndex出错");
            }
            videobase = CreateVideoSource(filename, GetFirstTrackOfType(index, TrackType.FFMS_TYPE_VIDEO, sb, 1000), index, string.Empty, Environment.ProcessorCount, 1, sb, 1000);
            if (videobase == IntPtr.Zero)
            {
                throw new Exception("CreateVideoSource出错");
            }
            IntPtr pVP = GetVideoProperties(videobase);
            if (pVP == IntPtr.Zero)
            {
                throw new Exception("GetVideoProperties出错");
            }
            //videoproperties = new VideoProperties();
            videoproperties = (VideoProperties)Marshal.PtrToStructure(pVP, typeof(VideoProperties));
            SetOutputFormat(videobase, PixelFormat.FFMS_PIX_FMT_BGR24, videoproperties.Width, videoproperties.Height, sb, 1000u);
        }
        public void CloseFile()
        {
            DestroyFrameIndex(index);
            DestroyVideoSource(videobase);
            index = IntPtr.Zero;
            videobase = IntPtr.Zero;
        }
        public Bitmap GetFrameBitmap(int n)
        {

            if (videobase == null)
                throw new Exception("GetFrameBitmap需要的videobase为null");
            StringBuilder sb = new StringBuilder(1000);
            IntPtr pAV = GetFrame(videobase, n, sb, 1000);
            FrameCache = (AVFrameLite)Marshal.PtrToStructure(pAV, typeof(AVFrameLite));
                
            BitmapData bitmapData = new BitmapData();
            bitmapData.Width = videoproperties.Width;
            bitmapData.Height = videoproperties.Height;
            bitmapData.PixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
            bitmapData.Stride = FrameCache.Linesize0;
            bitmapData.Scan0 = FrameCache.Data0;

            Bitmap output = new Bitmap(videoproperties.Width, videoproperties.Height);

            output.LockBits(new Rectangle(0, 0, output.Width, output.Height), ImageLockMode.WriteOnly | ImageLockMode.UserInputBuffer, System.Drawing.Imaging.PixelFormat.Format24bppRgb, bitmapData);
            output.UnlockBits(bitmapData);
            return output;
        }
        public Bitmap GetFrameBitmap(int n, Size size)
        {
            Bitmap b = GetFrameBitmap(n);
            Bitmap output = resizeBitmap(b, size.Width, size.Height);
            b.Dispose();
            return output;
        }
        public Bitmap resizeBitmap(Bitmap b, int nWidth, int nHeight)
        {
            Bitmap result = new Bitmap(nWidth, nHeight);
            using (Graphics g = Graphics.FromImage((Image)result))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
                g.DrawImage(b, 0, 0, nWidth, nHeight);
            }
            return result;
        }
        public double[] GetTimeCode()
        {
            if (index == IntPtr.Zero)
                return null;
            try
            {
                StringBuilder sb = new StringBuilder(1000);
                string tempfilename = Path.GetTempFileName();
                uint emsg = 1000u;
                //Init();
                //ffms2.IndexCallbackDelegate dcbd = new ffms2.IndexCallbackDelegate(invokec);
                //index = ffms2.MakeIndex(mkvmp4file, 0, 0, null, true, icd, IntPtr.Zero, sb, emsg);
                int trackNumber = ffms2.GetFirstTrackOfType(index, TrackType.FFMS_TYPE_VIDEO, sb, emsg);
                ffms2.WriteTimecodes(ffms2.GetTITrackIndex(index, trackNumber, sb, emsg), tempfilename, sb, emsg);

                List<double> listtc = new List<double>();
                double temp;
                StreamReader sr;

                sr = new StreamReader(tempfilename);
                if (sr.ReadLine().Trim().ToLower() != "# timecode format v2")
                    throw new Exception();
                while (sr.Peek() != -1)
                {
                    temp = 0;
                    double.TryParse(sr.ReadLine().Trim(), out temp);
                    listtc.Add(temp);
                }

                return listtc.ToArray();
            }
            finally
            {
                if (index != IntPtr.Zero)
                    FFMS2.ffms2.DestroyFrameIndex(index);
            }





        }



        ///Return Type: int
        ///State: int
        ///Current: __int64
        ///Total: __int64
        ///Private: void*
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate int IndexCallbackDelegate(int State, long Current, long Total, System.IntPtr Private);

        ///Return Type: void
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_Init@0", CallingConvention = CallingConvention.StdCall)]
        public static extern void Init();

        ///Return Type: VideoBase*
        ///SourceFile: char*
        ///Track: int
        ///TrackIndices: FrameIndex*
        ///PP: char*
        ///Threads: int
        ///SeekMode: int
        ///ErrorMsg: char*
        ///MsgSize: unsigned int
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_CreateVideoSource@32", CallingConvention = CallingConvention.StdCall)]
        public static extern System.IntPtr CreateVideoSource([In(), MarshalAs(UnmanagedType.LPStr)]
            string SourceFile, int Track, IntPtr TrackIndices, [In(), MarshalAs(UnmanagedType.LPStr)]
            string PP, int Threads, int SeekMode, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);

        ///Return Type: void
        ///VB: VideoBase*
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_DestroyVideoSource@4", CallingConvention = CallingConvention.StdCall)]
        public static extern void DestroyVideoSource(IntPtr VB);

        ///Return Type: VideoProperties*
        ///VB: VideoBase*
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_GetVideoProperties@4", CallingConvention = CallingConvention.StdCall)]
        public static extern System.IntPtr GetVideoProperties(IntPtr VB);

        ///Return Type: AVFrameLite*
        ///VB: VideoBase*
        ///n: int
        ///ErrorMsg: char*
        ///MsgSize: unsigned int
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_GetFrame@16", CallingConvention = CallingConvention.StdCall)]
        public static extern System.IntPtr GetFrame(IntPtr VB, int n, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);

        ///Return Type: void
        ///FI: FrameIndex*
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_DestroyFrameIndex@4", CallingConvention = CallingConvention.StdCall)]
        public static extern void DestroyFrameIndex(IntPtr FI);

        ///Return Type: int
        ///VB: VideoBase*
        ///TargetFormat: int
        ///Width: int
        ///Height: int
        ///ErrorMsg: char*
        ///MsgSize: unsigned int
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_SetOutputFormat@24", CallingConvention = CallingConvention.StdCall)]
        public static extern int SetOutputFormat(IntPtr VB, PixelFormat TargetFormat, int Width, int Height, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);


        ///Return Type: int
        ///TrackIndices: FrameIndex*
        ///TrackType: int
        ///ErrorMsg: char*
        ///MsgSize: unsigned int
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_GetFirstTrackOfType@16", CallingConvention = CallingConvention.StdCall)]
        public static extern int GetFirstTrackOfType(IntPtr TrackIndices, TrackType TrackType, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);
        ///Return Type: FrameInfoVector *
        ///TrackIndices: FrameIndex*
        ///TrackType: int
        ///ErrorMsg: char*
        ///MsgSize: unsigned int
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_GetTITrackIndex@16", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetTITrackIndex(IntPtr TrackIndices, int Track, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);

        ///Return Type: int
        ///FIV: FrameInfoVector*
        ///TimecodeFile: char*
        ///ErrorMsg: char*
        ///MsgSize: unsigned int
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_WriteTimecodes@16", CallingConvention = CallingConvention.StdCall)]
        public static extern int WriteTimecodes(IntPtr FIV, [In(), MarshalAs(UnmanagedType.LPStr)]
            string TimecodeFile, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);

        ///Return Type: FrameIndex*
        ///SourceFile: char*
        ///IndexMask: int
        ///DumpMask: int
        ///AudioFile: char*
        ///IgnoreDecodeErrors: boolean
        ///IP: IndexCallback
        ///Private: void*
        ///ErrorMsg: char*
        ///MsgSize: unsigned int

        [DllImport("ffms2.dll", EntryPoint = "_FFMS_MakeIndex@36", CallingConvention = CallingConvention.StdCall)]
        public static extern System.IntPtr MakeIndex([In(), MarshalAs(UnmanagedType.LPStr)]
            string SourceFile, int IndexMask, int DumpMask, [In(), MarshalAs(UnmanagedType.LPStr)]
            string AudioFile, [MarshalAs(UnmanagedType.I1)]
            bool IgnoreDecodeErrors, IndexCallbackDelegate IP, System.IntPtr Private, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);

        ///Return Type: FrameIndex*
        ///IndexFile: char*
        ///ErrorMsg: char*
        ///MsgSize: unsigned int
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_ReadIndex@12", CallingConvention = CallingConvention.StdCall)]
        public static extern System.IntPtr ReadIndex([In(), MarshalAs(UnmanagedType.LPStr)]
            string IndexFile, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);

        ///Return Type: int
        ///IndexFile: char*
        ///TrackIndices: FrameIndex*
        ///ErrorMsg: char*
        ///MsgSize: unsigned int
        [DllImport("ffms2.dll", EntryPoint = "_FFMS_WriteIndex@16", CallingConvention = CallingConvention.StdCall)]
        public static extern int WriteIndex([In(), MarshalAs(UnmanagedType.LPStr)]
            string IndexFile, IntPtr TrackIndices, [MarshalAs(UnmanagedType.LPStr)]
            StringBuilder ErrorMsg, uint MsgSize);



    }
    enum TrackType
    {
        FFMS_TYPE_VIDEO = 0,
        FFMS_TYPE_AUDIO = 1,
    };
    enum PixelFormat
    {
        FFMS_PIX_FMT_NONE = -1,
        FFMS_PIX_FMT_YUV420P,   ///< Planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
        FFMS_PIX_FMT_YUYV422,   ///< Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
        FFMS_PIX_FMT_RGB24,     ///< Packed RGB 8:8:8, 24bpp, RGBRGB...
        FFMS_PIX_FMT_BGR24,     ///< Packed RGB 8:8:8, 24bpp, BGRBGR...
        FFMS_PIX_FMT_YUV422P,   ///< Planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
        FFMS_PIX_FMT_YUV444P,   ///< Planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
        FFMS_PIX_FMT_RGB32,     ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in cpu endianness
        FFMS_PIX_FMT_YUV410P,   ///< Planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
        FFMS_PIX_FMT_YUV411P,   ///< Planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
        FFMS_PIX_FMT_RGB565,    ///< Packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), in cpu endianness
        FFMS_PIX_FMT_RGB555,    ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in cpu endianness most significant bit to 0
        FFMS_PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
        FFMS_PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black
        FFMS_PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white
        FFMS_PIX_FMT_PAL8,      ///< 8 bit with PIX_FMT_RGB32 palette
        FFMS_PIX_FMT_YUVJ420P,  ///< Planar YUV 4:2:0, 12bpp, full scale (jpeg)
        FFMS_PIX_FMT_YUVJ422P,  ///< Planar YUV 4:2:2, 16bpp, full scale (jpeg)
        FFMS_PIX_FMT_YUVJ444P,  ///< Planar YUV 4:4:4, 24bpp, full scale (jpeg)
        FFMS_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
        FFMS_PIX_FMT_XVMC_MPEG2_IDCT,
        FFMS_PIX_FMT_UYVY422,   ///< Packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
        FFMS_PIX_FMT_UYYVYY411, ///< Packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
        FFMS_PIX_FMT_BGR32,     ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in cpu endianness
        FFMS_PIX_FMT_BGR565,    ///< Packed RGB 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), in cpu endianness
        FFMS_PIX_FMT_BGR555,    ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in cpu endianness most significant bit to 1
        FFMS_PIX_FMT_BGR8,      ///< Packed RGB 3:3:2,  8bpp, (msb)2B 3G 3R(lsb)
        FFMS_PIX_FMT_BGR4,      ///< Packed RGB 1:2:1,  4bpp, (msb)1B 2G 1R(lsb)
        FFMS_PIX_FMT_BGR4_BYTE, ///< Packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)
        FFMS_PIX_FMT_RGB8,      ///< Packed RGB 3:3:2,  8bpp, (msb)2R 3G 3B(lsb)
        FFMS_PIX_FMT_RGB4,      ///< Packed RGB 1:2:1,  4bpp, (msb)2R 3G 3B(lsb)
        FFMS_PIX_FMT_RGB4_BYTE, ///< Packed RGB 1:2:1,  8bpp, (msb)2R 3G 3B(lsb)
        FFMS_PIX_FMT_NV12,      ///< Planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
        FFMS_PIX_FMT_NV21,      ///< as above, but U and V bytes are swapped

        FFMS_PIX_FMT_RGB32_1,   ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
        FFMS_PIX_FMT_BGR32_1,   ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness

        FFMS_PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian
        FFMS_PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian
        FFMS_PIX_FMT_YUV440P,   ///< Planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
        FFMS_PIX_FMT_YUVJ440P,  ///< Planar YUV 4:4:0 full scale (jpeg)
        FFMS_PIX_FMT_YUVA420P,  ///< Planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
    };


    [StructLayout(LayoutKind.Sequential)]
    struct AVFrameLite
    {

        ///BYTE*[4]
        public System.IntPtr Data0;
        public System.IntPtr Data1;
        public System.IntPtr Data2;
        public System.IntPtr Data3;

        ///int[4]
        public int Linesize0;
        public int Linesize1;
        public int Linesize2;
        public int Linesize3;

        ///BYTE*[4]
        public System.IntPtr Base0;
        public System.IntPtr Base1;
        public System.IntPtr Base2;
        public System.IntPtr Base3;

        ///int
        public int KeyFrame;

        ///int
        public int PictType;
    }
    [StructLayout(LayoutKind.Sequential)]
    struct VideoProperties
    {

        ///int
        public int Width;

        ///int
        public int Height;

        ///int
        public int FPSDenominator;

        ///int
        public int FPSNumerator;

        ///int
        public int NumFrames;

        ///int
        public PixelFormat PixelFormat;

        ///int
        public int SARNum;

        ///int
        public int SARDen;

        ///int
        public int CropTop;

        ///int
        public int CropBottom;

        ///int
        public int CropLeft;

        ///int
        public int CropRight;

        ///double
        public double FirstTime;

        ///double
        public double LastTime;
    }
    [StructLayout(LayoutKind.Sequential)]
    struct AudioProperties
    {
        int SampleRate;
        int Channels;
        int BitsPerSample;
        bool Float;
        long NumSamples;
    };
    [StructLayout(LayoutKind.Sequential)]
    struct TrackTimeBase
    {
        int Num;
        int Den;
    };


    /*
///    _AvisynthPluginInit2@4
_FFMS_ClosestFrameFromDTS@12
_FFMS_CreateAudioSource@20
_FFMS_CreateVideoSource@32
_FFMS_DestroyAudioSource@4
_FFMS_DestroyFrameIndex@4
_FFMS_DestroyVideoSource@4
_FFMS_FindClosestKeyFrame@16
_FFMS_FrameFromDTS@12
_FFMS_GetAudio@32
_FFMS_GetAudioProperties@4
_FFMS_GetFirstTrackOfType@16
_FFMS_GetFrame@16
_FFMS_GetFrameByTime@20
_FFMS_GetFrameInfo@16
_FFMS_GetNumFrames@4
_FFMS_GetNumTracks@4
_FFMS_GetTITrackIndex@16
_FFMS_GetTimeBase@4
_FFMS_GetTrackType@4
_FFMS_GetVSTrackIndex@4
_FFMS_GetVideoProperties@4
+_FFMS_Init@0
_FFMS_MakeIndex@36
_FFMS_ReadIndex@12
_FFMS_ResetOutputFormat@4
_FFMS_SetOutputFormat@24
_FFMS_WriteIndex@16
_FFMS_WriteTimecodes@16
    */
    /*

        public class FFMSVideoProvider : VideoProviderBase
        {
            private const int INDEX_FILE_VERSION_MIN = 8;
            private const int INDEX_FILE_VERSION_MAX = 11;

            ///Return Type: int
            ///State: int
            ///Current: __int64
            ///Total: __int64
            ///Private: void*
            [UnmanagedFunctionPointer(CallingConvention.StdCall)]
            private delegate int IndexCallbackDelegate(int State, long Current, long Total, System.IntPtr Private);

            private enum TrackType
            {

                ///FFMS_TYPE_VIDEO -> 0
                TYPE_VIDEO = 0,

                ///FFMS_TYPE_AUDIO -> 1
                TYPE_AUDIO = 1
            }

            private enum PixelFormat
            {

                ///FFMS_PIX_FMT_NONE -> -1
                PIX_FMT_NONE = -1,

                PIX_FMT_YUV420P,

                PIX_FMT_YUYV422,

                PIX_FMT_RGB24,

                PIX_FMT_BGR24,

                PIX_FMT_YUV422P,

                PIX_FMT_YUV444P,

                PIX_FMT_RGB32,

                PIX_FMT_YUV410P,

                PIX_FMT_YUV411P,

                PIX_FMT_RGB565,

                PIX_FMT_RGB555,

                PIX_FMT_GRAY8,

                PIX_FMT_MONOWHITE,

                PIX_FMT_MONOBLACK,

                PIX_FMT_PAL8,

                PIX_FMT_YUVJ420P,

                PIX_FMT_YUVJ422P,

                PIX_FMT_YUVJ444P,

                PIX_FMT_XVMC_MPEG2_MC,

                PIX_FMT_XVMC_MPEG2_IDCT,

                PIX_FMT_UYVY422,

                PIX_FMT_UYYVYY411,

                PIX_FMT_BGR32,

                PIX_FMT_BGR565,

                PIX_FMT_BGR555,

                PIX_FMT_BGR8,

                PIX_FMT_BGR4,

                PIX_FMT_BGR4_BYTE,

                PIX_FMT_RGB8,

                PIX_FMT_RGB4,

                PIX_FMT_RGB4_BYTE,

                PIX_FMT_NV12,

                PIX_FMT_NV21,

                PIX_FMT_RGB32_1,

                PIX_FMT_BGR32_1,

                PIX_FMT_GRAY16BE,

                PIX_FMT_GRAY16LE,

                PIX_FMT_YUV440P,

                PIX_FMT_YUVJ440P,

                PIX_FMT_YUVA420P
            }

            [StructLayout(LayoutKind.Sequential)]
            private struct AVFrameLite
            {

                ///BYTE*[4]
                public System.IntPtr Data0;
                public System.IntPtr Data1;
                public System.IntPtr Data2;
                public System.IntPtr Data3;

                ///int[4]
                public int Linesize0;
                public int Linesize1;
                public int Linesize2;
                public int Linesize3;

                ///BYTE*[4]
                public System.IntPtr Base0;
                public System.IntPtr Base1;
                public System.IntPtr Base2;
                public System.IntPtr Base3;

                ///int
                public int KeyFrame;

                ///int
                public int PictType;
            }


            [StructLayout(LayoutKind.Sequential)]
            private struct VideoProperties
            {

                ///int
                public int Width;

                ///int
                public int Height;

                ///int
                public int FPSDenominator;

                ///int
                public int FPSNumerator;

                ///int
                public int NumFrames;

                ///int
                public PixelFormat PixelFormat;

                ///int
                public int SARNum;

                ///int
                public int SARDen;

                ///int
                public int CropTop;

                ///int
                public int CropBottom;

                ///int
                public int CropLeft;

                ///int
                public int CropRight;

                ///double
                public double FirstTime;

                ///double
                public double LastTime;
            }


            private partial class FFMS
            {

            
            }


            VideoProperties _videoProperties;
            /// <summary>
            /// VideoBase
            /// </summary>
            /// <remarks></remarks>
            IntPtr _VS;
            AVFrameLite _currentFrameCache;
            List<int> _keyFrames;

            static FFMSVideoProvider()
            {
                FFMS.Init();
            }
            public override FrameType CurrentFrameType
            {
                get
                {
                    CheckDisposed();
                    DecodeCurrentFrame();
                    return _currentFrameCache.KeyFrame == 1 ? FrameType.Key : FrameType.Normal;
                }
            }

            public override int FrameCount
            {
                get
                {
                    CheckDisposed();
                    return _videoProperties.NumFrames;
                }
            }

            public override double FrameRate
            {
                get
                {
                    CheckDisposed();
                    return _videoProperties.FPSNumerator / _videoProperties.FPSDenominator;
                }
            }

            private void DecodeCurrentFrame()
            {
                //position hasn't been changed
                if (_currentFrameCache.Data0 != IntPtr.Zero)
                {
                    return;
                }
                var errorMsgCap = 1000;
                StringBuilder errorMsg = new StringBuilder(errorMsgCap);
                var framePtr = FFMS.GetFrame(_VS, CurrentFrameNumber, errorMsg, errorMsgCap);
                if (framePtr == IntPtr.Zero)
                {
                    ThrowException(errorMsg);
                }
                _currentFrameCache = (AVFrameLite)Marshal.PtrToStructure(framePtr, typeof(AVFrameLite));
            }
            public override void GetFrame(ref System.Drawing.Bitmap output)
            {
                CheckDisposed();
                DecodeCurrentFrame();

                if (output == null || output.PixelFormat != Imaging.PixelFormat.Format24bppRgb || output.Width != _videoProperties.Width || output.Height != _videoProperties.Height)
                {
                    if (output != null)
                    {
                        output.Dispose();
                    }
                    output = new Bitmap(_videoProperties.Width, _videoProperties.Height, _currentFrameCache.Linesize0, System.Drawing.Imaging.PixelFormat.Format24bppRgb, _currentFrameCache.Data0);
                    return;
                }
                var bitmapData = new BitmapData();
                bitmapData.Width = _videoProperties.Width;
                bitmapData.Height = _videoProperties.Height;
                bitmapData.PixelFormat = Imaging.PixelFormat.Format24bppRgb;
                bitmapData.Stride = _currentFrameCache.Linesize0;
                bitmapData.Scan0 = _currentFrameCache.Data0;

                output.LockBits(new Rectangle(0, 0, output.Width, output.Height), ImageLockMode.WriteOnly | ImageLockMode.UserInputBuffer, Imaging.PixelFormat.Format24bppRgb, bitmapData);
                output.UnlockBits(bitmapData);
            }

            public override void Open(string filePath)
            {
                CheckDisposed();
                Cleanup();
                if (!File.Exists(filePath))
                {
                    throw new FileNotFoundException();
                }
                string indexFile = Path.Combine(Path.GetTempPath(), string.Format("{0}.{1:X}.ffmsindex", Path.GetFileName(filePath), File.GetCreationTime(filePath).ToBinary() ^ File.GetLastWriteTime(filePath).ToBinary() ^ new FileInfo(filePath).Length));
                var tcFile = Path.ChangeExtension(indexFile, ".tc");
                IntPtr index = IntPtr.Zero;
                var errorMsgCap = 1000;
                StringBuilder errorMsg = new StringBuilder(errorMsgCap);
                //-----make or read index
                index = FFMS.ReadIndex(indexFile, errorMsg, errorMsgCap);
                if (index == IntPtr.Zero)
                {
                    errorMsg.Length = 0;
                    index = FFMS.MakeIndex(filePath, 0, 0, null, true, IndexCallback, IntPtr.Zero, errorMsg, errorMsgCap);
                    if (index == IntPtr.Zero)
                    {
                        ThrowException(errorMsg);
                    }
                    try
                    {
                        CheckResult(FFMS.WriteIndex(indexFile, index, errorMsg, errorMsgCap), errorMsg);
                    }
                    catch
                    {
                        FFMS.DestroyFrameIndex(index);
                        throw;
                    }
                    Helper.RegisterTempFile(indexFile);
                }
                try
                {
                    var trackNumber = FFMS.GetFirstTrackOfType(index, TrackType.TYPE_VIDEO, errorMsg, errorMsgCap);
                    if (trackNumber < 0)
                    {
                        throw new FFMSException("No video track found");
                    }
                    CheckResult(FFMS.WriteTimecodes(FFMS.GetTITrackIndex(index, trackNumber, errorMsg, errorMsgCap), tcFile, errorMsg, errorMsgCap), errorMsg);
                    //-----open video
                    _VS = FFMS.CreateVideoSource(filePath, trackNumber, index, string.Empty, Environment.ProcessorCount, 1, errorMsg, errorMsgCap);
                    if (_VS == IntPtr.Zero)
                    {
                        ThrowException(errorMsg);
                    }
                    IntPtr vpPtr = FFMS.GetVideoProperties(_VS);
                    _videoProperties = (VideoProperties)Marshal.PtrToStructure(vpPtr, typeof(VideoProperties));
                    //-----change output format if necessary
                    if (_videoProperties.PixelFormat != PixelFormat.PIX_FMT_BGR24)
                    {
                        CheckResult(FFMS.SetOutputFormat(_VS, PixelFormat.PIX_FMT_BGR24, _videoProperties.Width, _videoProperties.Height, errorMsg, errorMsgCap), errorMsg);
                    }
                }
                finally
                {
                    FFMS.DestroyFrameIndex(index);
                }
                GetKeyFrameList(indexFile);
                SetTimecodes(Timecodes.OpenV2(tcFile));
                File.Delete(tcFile);
            }

            private void GetKeyFrameList(string indexFile)
            {
                _keyFrames = new List<int>();
                using (fs == File.OpenRead(indexFile))
                {
                }
            }
        }*/
}
#endif